package cn.zjj.basic.service.impl;

import cn.zjj.basic.constans.VerifyCodeConstants;
import cn.zjj.basic.dto.SmsCodeDto;
import cn.zjj.basic.exception.BusinessException;
import cn.zjj.basic.service.IVerifyCodeService;
import cn.zjj.basic.util.SmsUtil;
import cn.zjj.basic.util.StrUtils;
import cn.zjj.basic.util.VerifyCodeUtils;
import cn.zjj.user.domain.User;
import cn.zjj.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    //注入redis
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;
    @Override
    public String getImgCode(String code) {

        if(StringUtils.isEmpty(code)){
            throw new BusinessException("参数异常");
        }
        //1.生成验证码
        String complexRandomString = StrUtils.getComplexRandomString(4);
        //2.放入redis中   并设置过期时间为3分钟
        redisTemplate.opsForValue().set(code,complexRandomString,3, TimeUnit.MINUTES);
        //3.将验证码转为base64位 图片字符串,并返回
        return VerifyCodeUtils.verifyCode(100, 40, complexRandomString);
    }

    //获取短信验证码
    @Override
    public void sendSmsCode(SmsCodeDto msCodeDto) {
        //图片验证码value(用户写的)
        String imageCode = msCodeDto.getImageCode();
        //图片验证码key
        String imageCodeKey = msCodeDto.getImageCodeKey();
        //用户填写的手机号
        String phone = msCodeDto.getPhone();


        /**
         * 1.校验空值
         */
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号为空!");
        } else if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请重新获取图形验证码!");
        } else if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("图形验证码为空!");
        }
        /**
         * 2.图形验证码过期校验
         */
        if(redisTemplate.opsForValue().get(imageCodeKey)==null){
            throw new BusinessException("图形验证码过期,请重新获取!");
        }

        /**
         * 3.图片验证码信息校验 (用户的value和redis中的value对比)
         */
        //获取redis中对应key的value,并和用户的value比较
        Object o = redisTemplate.opsForValue().get(imageCodeKey);
        if(!imageCode.equalsIgnoreCase(o.toString())){
                throw new BusinessException("图片验证码不一致.请重新输入");
        }
        /**
         * 4.校验手机号是否注册过
         */
        User user = userMapper.selectByPhone(phone);
        if(user!=null){
            throw new BusinessException("此手机号已经注册,请更换!");
        }
        /**
         * //4.判断原来的验证码是否有效【3分钟过期 - redis】，从redis是否能拿到通过key【register:18708146200】
         * //4.1.如果拿到了，表示有效,继续判断是否过了1分钟重发时间 value【9527:14688777777711】
         * 		//4.1.1.如果没有过，就不应该再发，提示错误 - 请勿重发验证码
         * 		//4.1.2.如果过了，就使用上次的验证码，但是要刷新过期时间【重新添加resis，用新的时间戳】
         */
        //如果不为空  (key值为"phone+:register")   手机:业务   防止以后其他需要用手机验证码时复用出错
        Object  o1 = redisTemplate.opsForValue().get(VerifyCodeConstants.REGISTER_CODE_PREFIX + phone);
        String PhoneCode=null;
        if(o1!=null){
            String phoneCodeValue = o1.toString();
            //判断重发时间是否大于 60 s,获得value
            //9999:时间戳
            String[] split = phoneCodeValue.split(":");

            //上次获得验证码的时间戳
            Long oldTime = Long.valueOf(split[1]);
            //当前时间戳减上次的时间戳,重发时间
            long LetTime = System.currentTimeMillis() - oldTime;
            //判断是否大于60s
            if(LetTime<=1*60*1000){//<=60s
                throw new BusinessException("系统繁忙,请稍后重试!");
            }else{
                //上次的验证码,过了验证时间才获取其中的value ,才发送
                PhoneCode = split[0];
            }
        }else {
            //4.2.如果没有拿到，表示验证码过期了
                //4.2.1.重新生成验证码，并添加到redis
            PhoneCode = StrUtils.getComplexRandomString(6);
        }
        //设置成 key:   "register:phone","code:时间戳"      过期时间3分钟(如果进了if就相当于重置过期时间)
        redisTemplate.opsForValue().set(VerifyCodeConstants.REGISTER_CODE_PREFIX+phone,PhoneCode+":"+System.currentTimeMillis(),100,TimeUnit.MINUTES);
        //5.调用短信接口发送短信
        /*SmsUtil.sendSms(phone,"您的验证码为:"+PhoneCode);*/
        System.out.println("您的验证码为："+PhoneCode+",请在三分钟之内使用");

    }
    //绑定账户时发送验证码
    @Override
    public void binderSmsCode(String phone) {

        /**
         * 1.校验空值
         */
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("请输入手机号");
        }
        Object o2 = redisTemplate.opsForValue().get(VerifyCodeConstants.BINDER_CODE_PREFIX + phone);
        //如果不为空  (key值为"phone+:register")   手机:业务   防止以后其他需要用手机验证码时复用出错
        String PhoneCode=null;
        if(o2!=null){
            String phoneCodeValue =  o2.toString();
            //判断重发时间是否大于 60 s
            //9999:时间戳
            String[] split = phoneCodeValue.split(":");

            //上次获得验证码的时间戳
            Long oldTime = Long.valueOf(split[1]);
            //当前时间戳减上次的时间戳,重发时间
            long LetTime = System.currentTimeMillis() - oldTime;
            //判断是否大于60s
            if(LetTime<=1*60*1000){//<=60s
                throw new BusinessException("系统繁忙,请稍后重试!");
            }else{
                //上次的验证码,过了验证时间才获取其中的value ,才发送
                PhoneCode = split[0];
            }
        }else {
            //4.2.如果没有拿到，表示验证码过期了
            //4.2.1.重新生成验证码，并添加到redis
            PhoneCode = StrUtils.getComplexRandomString(6);
        }
        //设置成 key:   "register:phone","code:时间戳"      过期时间3分钟(如果进了if就相当于重置过期时间)
        redisTemplate.opsForValue().set(VerifyCodeConstants.BINDER_CODE_PREFIX+phone,PhoneCode+":"+System.currentTimeMillis(),100,TimeUnit.MINUTES);
        //5.调用短信接口发送短信
        /*SmsUtil.sendSms(phone,"您的验证码为:"+PhoneCode);*/
        System.out.println("您的验证码为："+PhoneCode+",请在三分钟之内使用");


    }
}
